package net.pulseproject.router.debuggerapp.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.WindowConstants;

import net.pulseproject.commons.gui.ActionListenerX;
import net.pulseproject.commons.gui.IconsCache;
import net.pulseproject.commons.midi.DebuggerLogic;
import net.pulseproject.commons.midi.entity.Device;
import net.pulseproject.commons.util.GuiUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.inject.Inject;

public class MainWindowImpl extends JFrame implements MainWindow {

	private static final Log LOG = LogFactory.getLog(MainWindowImpl.class);
	private static final long serialVersionUID = -127345357427962973L;
	
	private static final Font TITLE_FONT = new Font(Font.DIALOG, Font.BOLD, 12);
	
	private final DebuggerLogic logic;
	private final Set<Device> devicePanelCreated = new HashSet<Device>();
	private final Map<Device, JPanel> containerPanelsByDevice = new HashMap<Device, JPanel>();
	private final IconsCache iconsCache;
	
	@Inject
	public MainWindowImpl(final IconsCache iconsCache, final DebuggerLogic logic) {
		super("Pulse Debugger");
		LOG.debug("new MainWindow()");
		this.iconsCache = iconsCache;
		this.logic = logic;
	}

	@Override
	public final void startUp(final Collection<Device> transmitters, final Collection<Device> receivers) {
		this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		
		final JPanel mainPanel = new JPanel();
		mainPanel.setLayout(new BorderLayout());
		final JScrollPane chooserScroll = new JScrollPane(this.createChoosePanel(transmitters, receivers));
		chooserScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		mainPanel.add(chooserScroll, BorderLayout.WEST);
		
		final Collection<Device> allDevices = new LinkedList<Device>();
		allDevices.addAll(transmitters);
		allDevices.addAll(receivers);
		mainPanel.add(new JScrollPane(this.createContentPanel(allDevices)), BorderLayout.CENTER);
		this.add(mainPanel);
		
		this.setSize(900, 500);
		GuiUtil.setCenterLocation(this);
	}
	
	private JPanel createChoosePanel(final Collection<Device> transmitters, final Collection<Device> receivers) {
		final JPanel panel = new JPanel();
		panel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		this.createChooseContent(panel, transmitters, "Transmitters");
		
		final JPanel gap = new JPanel();
		gap.setMinimumSize(new Dimension(1, 20));
		gap.setMaximumSize(new Dimension(999, 20));
		panel.add(gap);
		
		this.createChooseContent(panel, receivers, "Receivers");
		
		return panel;
	}
	
	private void createChooseContent(final JPanel panel, final Collection<Device> devices, final String title) {
		final JLabel lbl = new JLabel(title);
		lbl.setFont(TITLE_FONT);
		panel.add(lbl);
		
		for (final Device device : devices) {
			final JCheckBox checkBox = new JCheckBox(device.getPortName());
			
			checkBox.addActionListener(new ActionListenerX(this.iconsCache, this, "Toggling device [" + device + "] failed!") {
				@Override protected void action(final ActionEvent event) {
					MainWindowImpl.this.onDeviceCheckBoxClicked(device, checkBox.isSelected());
				}
			});
			panel.add(checkBox);
		}
	}
	
	private JPanel createContentPanel(final Collection<Device> allDevices) {
		final JPanel panel = new JPanel();
		final FlowLayout layout = new FlowLayout(FlowLayout.LEADING, 0, 0);
		panel.setLayout(layout);
		for (final Device device : allDevices) {
			final JPanel containerPanel = new JPanel();
			containerPanel.setVisible(false);
//			containerPanel.setBackground(RandomUtil.randomColor());
			this.containerPanelsByDevice.put(device, containerPanel);
			panel.add(containerPanel);
		}
		
		return panel;
	}
	
	private void onDeviceCheckBoxClicked(final Device device, final boolean selected) {
		LOG.debug("onDeviceCheckBoxClicked(device=" + device + ", selected=" + selected + ")");
		
		final JPanel containerPanel = this.containerPanelsByDevice.get(device);
		
		if(selected == true && this.devicePanelCreated.contains(device) == false) {
			final DevicePanel devicePanel = new DevicePanel(this.iconsCache, this, this.logic, device);
			containerPanel.add(devicePanel);
			this.devicePanelCreated.add(device);
		}
		
		containerPanel.setVisible(selected);
		this.validate();
	}
}
